﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Automation.Peers;
using ATEC.ATCore;
using ATEC.ATDataCoreNET;
using ATEC.GeometryNET;
using ATEC.Windowing;
using SSDPNET.DataCore;
using SSDPObject;

namespace ViewExample
{
    /// <summary>
    /// 类名：UsingViewMethods
    /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作
    /// 功能：展示视口的基本操作，包括视口的打开关闭、场景关联、视图调整、监控和渲染等功能。
    /// 关键类及说明：
    ///     - ATView：视口操作类，提供视口的基本操作功能
    ///     - IViewManager：视口管理器，管理视口的生命周期和事件
    ///     - IndexedViewport：索引视口类，表示具体的视口实例
    ///     - ATSceneRef：场景引用类，管理场景对象
    /// </summary>
    public class UsingViewMethods
    {
        /// <summary>
        /// 方法名：ViewOpen
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/基本操作
        /// 功能：打开所有可用的视口（0-9号视口）。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     遍历视口索引并尝试打开每个视口；
        ///     如果打开失败，会显示对应的错误提示。
        /// </summary>
        public static void ViewOpen()
        {
            int[] windowIdx = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            foreach ( int i in windowIdx)
            {
                int nErrorCode = SSDPNET.ATView.ViewTurnOn(i);
                if ( nErrorCode != 0)
                {
                    System.Windows.Forms.MessageBox.Show($"第{i+1}个视口打开失败");
                }
            }
        }

        /// <summary>
        /// 方法名：ViewClose
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/基本操作
        /// 功能：关闭当前激活的视口。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     获取当前选中的视口索引并关闭该视口；
        ///     操作完成后显示关闭成功的提示信息。
        /// </summary>
        public static void ViewClose()
        {
            int nIdx = SSDPNET.WindowFuncs.WindowGetSelectedViewIndex();
            SSDPNET.ATView.ViewTurnOff(nIdx);

            System.Windows.Forms.MessageBox.Show($"视口关闭成功，被关闭的视口index:{nIdx}");
        }

        /// <summary>
        /// 方法名：ViewRestore
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/基本操作
        /// 功能：恢复默认的视口布局（保留0-2号视口）。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     先关闭所有视口（0-7号），然后只打开默认的三个视口（0-2号）。
        /// </summary>
        public static void ViewRestore()
        {
            int[] windowIdx = { 0, 1, 2, 3, 4, 5, 6, 7 };

            foreach (int i in windowIdx)
            {
                int nErrorCode = SSDPNET.ATView.ViewTurnOff(i);
            }

            int[] defaultIdx = { 0, 1, 2};

            foreach (int i in defaultIdx)
            {
                int nErrorCode = SSDPNET.ATView.ViewTurnOn(i);
            }
        }

        /// <summary>
        /// 方法名：ViewManagerAddTransients
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/瞬态绘制
        /// 功能：开启视口的瞬态绘制功能。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     添加瞬态绘制处理器，用于在视口中显示临时图形。
        /// </summary>
        public static void ViewManagerAddTransients()
        {
            SSDPNET.IViewManager m = SSDPNET.IViewManager.GetManager();
            m.AddViewTransientHandler(DrawTransient);
        }
        
        /// <summary>
        /// 方法名：ViewManagerDropTransients
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/瞬态绘制
        /// 功能：关闭视口的瞬态绘制功能。
        /// 参数：无
        /// 返回值：无
        /// </summary>
        public static void ViewManagerDropTransients()
        {
            SSDPNET.IViewManager m = SSDPNET.IViewManager.GetManager();
            m.DropViewTransientHandler(DrawTransient);
        }

        /// <summary>
        /// 方法名：DrawTransient
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/瞬态绘制
        /// 功能：在当前视口中为所有线性图元的起点绘制切向箭头。
        /// 参数：
        ///     - pContext：ATViewContxt，视口上下文
        ///     - bUpdate：bool，是否更新显示
        /// 返回值：无
        /// 关键类及说明：
        ///     - IViewDraw：视图绘制接口，提供基本绘制功能
        ///     - ObjectMatSymbology：材质符号类，控制绘制的颜色和填充
        /// </summary>
        public static void DrawTransient(ATEC.ATDataCoreNET.ATViewContxt pContext, bool bUpdate)
        {
            ATEC.ATDataCoreNET.IViewDraw pDraw = pContext.GetIViewDraw();

            ATEC.ATDataCoreNET.ObjectMatSymbology eM = pContext.GetObjectMatSymbology();

            eM.IsFilled = true;
            eM.LineColor = 220;
            eM.FillColor = 220;

            pDraw.ActivateMatSymbology(eM);//箭头颜色将绘制为红色

            ATEC.ATDataCoreNET.ATSceneRef currentS = pContext.GetCurrentScene();
            ATEC.ATDataCoreNET.SceneObjectsCollection graphics = currentS.AsATScenes().GetGraphicObjects();//得到当前Scen中所有可视对象

            foreach ( var oneCrv in graphics )
            {
                ATEC.GeometryNET.CurveSet curve = ATEC.ATDataCoreNET.ATObjects.CurvePathQuery.ObjectToCurveSet(oneCrv);

                if ( curve != null )
                {
                    ATEC.GeometryNET.XPoint3d ptS;
                    ATEC.GeometryNET.XVector3d dirT;

                    ATEC.GeometryNET.BasicCurve crv = curve.GetAt(0);
                    crv.FractionToPoint(0.0, out ptS, out dirT);
                    dirT.NormalizeInPlace();

                    ATEC.GeometryNET.XPoint3d ptE = ptS + 200* dirT;
                    ATEC.GeometryNET.XPoint3d ptEE = ptE + 200 * dirT;

                    pDraw.DrawCone( ptS, ptE, 40.0, 40.0, true);//箭头圆柱体部分
                    pDraw.DrawCone( ptE, ptEE, 80.0, 0.0, true);//箭头圆锥体部分
                }
            }
        }

        /// <summary>
        /// 方法名：ViewManagerAddViewOpenMonitor
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/监控
        /// 功能：添加视口打开事件的监控。
        /// 参数：无
        /// 返回值：无
        /// </summary>
        public static void ViewManagerAddViewOpenMonitor()
        {
            SSDPNET.IViewManager m = SSDPNET.IViewManager.GetManager();
            m.AddOnViewOpenHandler(ViewOpenBroadCast);
        }
        
        /// <summary>
        /// 方法名：ViewManagerDropViewOpenMonitor
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/监控
        /// 功能：移除视口打开事件的监控。
        /// 参数：无
        /// 返回值：无
        /// </summary>
        public static void ViewManagerDropViewOpenMonitor()
        {
            SSDPNET.IViewManager m = SSDPNET.IViewManager.GetManager();
            m.DropOnViewOpenHandler(ViewOpenBroadCast);
        }

        /// <summary>
        /// 方法名：ViewOpenBroadCast
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/监控
        /// 功能：视口打开事件的处理函数。
        /// 参数：
        ///     - pVp：Viewport，被打开的视口对象
        /// 返回值：无
        /// </summary>
        private static void ViewOpenBroadCast(ATEC.ATDataCoreNET.Viewport pVp)
        {
            System.Windows.Forms.MessageBox.Show("视口打开时，正在调用ViewMonitorAdd添加的函数");
        }

        /// <summary>
        /// 方法名：GetVpFromScene
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/工具
        /// 功能：通过场景对象查找关联的视口。
        /// 参数：
        ///     - sc：ATSceneRef，要查找的场景对象
        /// 返回值：IndexedViewport，找到的视口对象，如果未找到则返回null
        /// </summary>
        public static ATEC.ATDataCoreNET.IndexedViewport GetVpFromScene(ATEC.ATDataCoreNET.ATSceneRef sc)
        {


            SSDPNET.IndexedViewSet viewSet = SSDPNET.IViewManager.GetActiveViewSet();
            int[] windowIdx = { 0, 1, 2, 3, 4, 5, 6, 7 };
            foreach (int idx in windowIdx)
            {
                var vp = viewSet.GetViewport(idx);
                if (vp != null)
                {
                    var oneSc = vp.GetTargetScene();
                    if (oneSc == sc)
                    {
                        return vp;
                    }
                }
            }
            return null;
        }
        
        /// <summary>
        /// 方法名：ChangeBackgroundColor
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/外观
        /// 功能：修改当前视口的背景颜色。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     获取当前视口的背景色并进行调整；
        ///     新颜色通过对RGB分量分别增加不同值来生成。
        /// </summary>
        public static void ChangeBackgroundColor()
        {
            int nIdx = SSDPNET.WindowFuncs.WindowGetSelectedViewIndex();

            SSDPNET.IndexedViewSet viewSet = SSDPNET.IViewManager.GetActiveViewSet();

            ATEC.ATDataCoreNET.IndexedViewport vp = viewSet.GetViewport(nIdx);
            viewSet.SetSelectedView(vp, true, true);

            ATEC.ATDataCoreNET.RgbColorDef bgColor = vp.GetViewInformation().GetBackgroundColor();

            //新颜色设置为将旧的rgb分量加32,16,8
            bgColor.R += 32;
            bgColor.G += 16;
            bgColor.B += 8;

            //用255取余
            bgColor.R %= 255;
            bgColor.G %= 255;
            bgColor.B %= 255;

            var viewF = vp.GetViewInformation().ViewFlags;
            vp.GetViewInformation().SetBackgroundColor(bgColor);

            // 更换背景颜色时需要置位OverrideBackground
            viewF.OverrideBackground = true;
            viewF.AuxDisplay = true;
            viewF.RenderMode = 0;

            vp.GetViewInformation().SetViewFlags(viewF);

            vp.SynchWithViewInformation(true, true);

            // 更新视口
            SSDPNET.ATView.ViewUpdateSingle(nIdx);
        }

        /// <summary>
        /// 方法名：CreateNewScene
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/场景
        /// 功能：创建新的场景并在其中生成一条直线。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     创建名为"newScene"的新场景；
        ///     在场景中创建一条从原点到(10000,10000,0)的直线。
        /// </summary>
        public static void CreateNewScene()
        {
            string name = "newScene";
            ATEC.ATDataCoreNET.ATSceneRef scenR = SSDPNET.ScenesFunctions.SceneRefGetActive();

            ATEC.ATDataCoreNET.SceneID mdId = scenR.GetATProject().FindSceneIdByName(name);
            if (mdId > 0)
            {
                System.Windows.Forms.MessageBox.Show("newScene已经存在于当前工程！");
                return;
            }

            ATEC.ATDataCoreNET.ATScenesStatus err;
            //创建new scene
            scenR.GetATProject().CreateNewScene(out err, name, ATEC.ATDataCoreNET.ATScenesType.Normal, true, scenR.AsATScenes());

            //加载new scene
            mdId = scenR.GetATProject().FindSceneIdByName(name);
            ATEC.ATDataCoreNET.StatusInt errorDetails = new ATEC.ATDataCoreNET.StatusInt();
            ATEC.ATDataCoreNET.ATScene newS = scenR.GetATProject().LoadRootSceneById(ref errorDetails, mdId);

            ATEC.GeometryNET.XPoint3d ptB = ATEC.GeometryNET.XPoint3d.Zero;
            ATEC.GeometryNET.XPoint3d ptU = ATEC.GeometryNET.XPoint3d.Zero;
            ptU.X = 10000;
            ptU.Y = 10000;

            ATEC.GeometryNET.CurveSet curveSetNew = ATEC.GeometryNET.CurveSet.Create(ATEC.GeometryNET.CurveSet.BoundaryType.Open);
            curveSetNew.Add(ATEC.GeometryNET.BasicCurve.CreateLine(new ATEC.GeometryNET.XSegment3d(ptB, ptU)));

            //在新建的Scen 中创建一个直线
            ATEC.ATDataCoreNET.ATObjects.ATObject curveSetObj = ATEC.ATDataCoreNET.ATObjects.GeometryToATObject.ToObject(newS, curveSetNew, null);
            curveSetObj.AddToScene();
        }

        /// <summary>
        /// 方法名：SetDefaultScene
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/场景
        /// 功能：将默认场景关联到当前视口。
        /// 参数：无
        /// 返回值：无
        /// </summary>
        public static void SetDefaultScene()
        {
            ATEC.ATDataCoreNET.ATSceneRef scenR = SSDPNET.ScenesFunctions.SceneRefGetActive();
            ATEC.ATDataCoreNET.SceneID mdId = scenR.GetATProject().DefaultSceneId;

            ATEC.ATDataCoreNET.StatusInt errorDetails = new ATEC.ATDataCoreNET.StatusInt();
            ATEC.ATDataCoreNET.ATScene newS = scenR.GetATProject().LoadRootSceneById(ref errorDetails, mdId);

            int nIdx = SSDPNET.WindowFuncs.WindowGetSelectedViewIndex();

            // 关联新的视口和Scene
            SSDPNET.ATView.ViewSetScene(newS, nIdx);
        }

        /// <summary>
        /// 方法名：SetNewScene
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/场景
        /// 功能：将新创建的场景关联到当前视口。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     检查"newScene"是否存在，如果存在则关联到当前视口。
        /// </summary>
        public static void SetNewScene()
        {
            ATEC.ATDataCoreNET.ATSceneRef scenR = SSDPNET.ScenesFunctions.SceneRefGetActive();

            string name = "newScene";
            ATEC.ATDataCoreNET.SceneID mdId = scenR.GetATProject().FindSceneIdByName(name);

            if (mdId < 0)
            {
                System.Windows.Forms.MessageBox.Show("newScene还未被创建！");
                return;
            }

            ATEC.ATDataCoreNET.StatusInt errorDetails = new ATEC.ATDataCoreNET.StatusInt();
            ATEC.ATDataCoreNET.ATScene newS = scenR.GetATProject().LoadRootSceneById(ref errorDetails, mdId);

            int nIdx = SSDPNET.WindowFuncs.WindowGetSelectedViewIndex();

            // 关联新的视口和Scene
            SSDPNET.ATView.ViewSetScene(newS, nIdx);
        }

        /// <summary>
        /// 方法名：FitView
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/视图
        /// 功能：调整视口显示范围以适应当前场景内容。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     计算场景的空间范围并调整视口显示区域；
        ///     居中显示并刷新视图。
        /// </summary>
        public static void FitView()
        {
            SSDPNET.IndexedViewSet viewSet = SSDPNET.IViewManager.GetActiveViewSet();
            ATEC.ATDataCoreNET.IndexedViewport viewport = viewSet.GetSelectedViewport();

            ATEC.GeometryNET.XRange3d sceneRange;
            ATEC.ATDataCoreNET.ATSceneRef scene = SSDPNET.ScenesFunctions.SceneRefGetActive();

            // 计算当前scen所在的空间范围
            if (viewport.ComputeDisplayedSceneRefRange(out sceneRange, scene, true) != ATEC.ATDataCoreNET.StatusInt.Success )
            {
                return;
            }

            // 将当前视口范围调整到scen所在的空间范围
            if (viewport.ChangeAreaFromFit( sceneRange.Low, sceneRange.High, false, true) != ATEC.ATDataCoreNET.StatusInt.Success)
            {
                return;
            }

            viewport.CenterScrollBar();
            viewport.ForceHealImmediate(500);
        }
        
        /// <summary>
        /// 方法名：ModifyRenderMode
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/渲染
        /// 功能：修改当前视口的渲染模式为平滑着色。
        /// 参数：无
        /// 返回值：无
        /// </summary>
        public static void ModifyRenderMode()
        {
            int nIdx = SSDPNET.WindowFuncs.WindowGetSelectedViewIndex();
            SSDPNET.IndexedViewSet viewSet = SSDPNET.IViewManager.GetActiveViewSet();
            ATEC.ATDataCoreNET.IndexedViewport vp = viewSet.GetViewport(nIdx);
            var viewF = vp.GetViewInformation().ViewFlags;
            viewF.RenderMode = (int)ATRenderMode.SmoothShade;//修改渲染模式
            vp.GetViewInformation().SetViewFlags(viewF);
            //更新视口
            SSDPNET.ATView.ViewUpdateSingle(nIdx);
     
        }

        /// <summary>
        /// 方法名：RotateView
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/视图
        /// 功能：将当前视口旋转到前视图方向。
        /// 参数：无
        /// 返回值：无
        /// </summary>
        public static void RotateView()
        {
            int nIdx = SSDPNET.WindowFuncs.WindowGetSelectedViewIndex();
            XMatrix3d rotation = XMatrix3d.Identity;
            ATEC.ATDataCoreNET.StandardView standardViewId = ATEC.ATDataCoreNET.StandardView.Front;

            ViewInformation.GetStandardViewByName(out rotation, out standardViewId, "前视图");
            SSDPNET.ATView.ViewRotateToRMatrix(rotation, nIdx);//修改为前视图
            //更新视口
            SSDPNET.ATView.ViewUpdateSingle(nIdx);
        }

        /// <summary>
        /// 方法名：AdapterWindow
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/窗口
        /// 功能：创建一个悬浮窗体。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     通过反射加载ATLoadNet.dll并创建悬浮窗体；
        ///     窗体将独立于主程序窗口显示。
        /// </summary>
        public static void AdapterWindow()
        {
            AdapterWindow adapter = new AdapterWindow();
            adapter.Text = "悬浮窗体";

            //窗体独立悬浮显示
            string ssdpDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string dllPath = Path.Combine(ssdpDir, "ATLoadNet.dll");
            Assembly assembly = Assembly.LoadFrom(dllPath);
            Type atLoadType = assembly.GetType("ATLoadNet.ATLoadNet");
            if (atLoadType == null)
                return;

            MethodInfo getAppMethodInfo = atLoadType?.GetMethod("GetApp", BindingFlags.Static | BindingFlags.Public);
            if (getAppMethodInfo != null)
            {
                // 调用GetApp静态方法，并假设它返回SomeClass类型  
                // 注意：如果方法实际上返回的是其他类型（如object），你需要进行类型转换  
                ATLoad result = (ATLoad)getAppMethodInfo.Invoke(null, null); // 静态方法不需要实例，所以第一个参数为null  
                adapter.AttachAsTopLevelForm(result, true);
                adapter.Show();

            }

        }
        /// <summary>
        /// 方法名：DockWindow
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/视口操作/窗口
        /// 功能：创建一个停靠窗体。
        /// 参数：无
        /// 返回值：无
        /// 说明：
        ///     创建新窗体并将其停靠在主窗口的右侧。
        /// </summary>
        public static void DockWindow()
        {
            AdapterWindow adapter = new AdapterWindow();
            adapter.Text = "停靠窗体";

            //窗体停靠显示
            ATEC.Windowing.WindowManager windowManager = ATEC.Windowing.WindowManager.GetForATECStation();
            windowManager.DockPanel(adapter, 1, adapter.Text, DockLocation.Right);
        }
    }
}